package com.luo.d3s.light.mybatis.ec.domain.goods;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.luo.d3s.core.application.dto.PageResponse;
import com.luo.d3s.core.infrastructure.convertor.MpPageConvertor;
import com.luo.d3s.ext.component.bus.DomainRegistry;
import com.luo.d3s.light.mybatis.ec.application.dto.query.GoodsPageQuery;
import com.luo.d3s.light.mybatis.ec.application.dto.vo.GoodsVo;
import com.luo.d3s.light.mybatis.ec.domain.base.BaseRepository;
import com.luo.d3s.light.mybatis.ec.infrastructure.database.dao.GoodsTagBindingMapper;
import com.luo.d3s.light.mybatis.ec.infrastructure.database.databoject.GoodsTagBindingDo;
import org.apache.ibatis.annotations.Param;

import java.util.*;
import java.util.function.Function;

/**
 * 商品仓库
 *
 * @author luohq
 * @date 2022-12-21
 */
public interface GoodsRepository extends BaseRepository<Goods> {

    @Override
    default Goods save(Goods aggregateRoot) {
        //保存商品基础信息
        BaseRepository.super.save(aggregateRoot);

        //处理商品、标签绑定关系
        GoodsTagBindingMapper goodsTagBindingMapper = DomainRegistry.getBean(GoodsTagBindingMapper.class);
        //删除原绑定关系
        goodsTagBindingMapper.deleteByGoodsIds(Collections.singletonList(aggregateRoot.getId()));
        //批量保存新的绑定关系
        if (Objects.nonNull(aggregateRoot.getTags()) && !aggregateRoot.getTags().isEmpty()) {
            aggregateRoot.getTags().stream()
                    .map(tagId -> new GoodsTagBindingDo(aggregateRoot.getId(), tagId))
                    .forEach(goodsTagBindingMapper::insert);
        }
        return aggregateRoot;
    }

    @Override
    default Goods findById(Long id) {
        //查询商品信息
        Goods goods = BaseRepository.super.findById(id);

        //查询商品绑定的标签
        GoodsTagBindingMapper goodsTagBindingMapper = DomainRegistry.getBean(GoodsTagBindingMapper.class);
        Set<Long> tagIds = Optional.ofNullable(goodsTagBindingMapper.findTagIdsOfGoods(id)).orElse(Collections.emptySet());
        //设置商品标签
        goods.modifyTags(tagIds);
        //返回商品信息
        return goods;
    }

    @Override
    default Boolean exists(Long id) {
        return BaseRepository.super.exists(id);
    }

    @Override
    default Integer removeById(Long id) {
       return this.removeByIds(Collections.singletonList(id));
    }

    @Override
    default Integer removeByIds(Collection<Long> ids) {
        //删除商品绑定的标签
        GoodsTagBindingMapper goodsTagBindingMapper = DomainRegistry.getBean(GoodsTagBindingMapper.class);
        goodsTagBindingMapper.deleteByGoodsIds(ids);
        //删除商品信息
        return BaseRepository.super.removeByIds(ids);
    }


    /**
     * 标签下是否存在商品
     *
     * @param tagIds 标签ID列表
     * @return 是否存在
     */
    default Boolean existsByTagIds(Collection<Long> tagIds) {
        GoodsTagBindingMapper goodsTagBindingMapper = DomainRegistry.getBean(GoodsTagBindingMapper.class);
        return goodsTagBindingMapper.existByTagIds(tagIds);
    }

    /**
     * 分类下是否存在商品
     *
     * @param categoryIds 分类ID列表
     * @return 是否存在
     */
    default Boolean existGoodsInCategories(List<Long> categoryIds) {
        //验证分类ID集合是否存在商品
        return this.exists(Wrappers.<Goods>lambdaQuery()
                .in(Goods::getCategoryId, categoryIds)
        );
    }

    /**
     * 是否存在上架状态的商品
     *
     * @param goodsIds 商品ID列表
     * @return 是否存在
     */
    default Boolean existGoodsShelved(List<Long> goodsIds) {
        //验证是否存在上架状态的商品
        return this.exists(Wrappers.<Goods>lambdaQuery()
                .in(Goods::getId, goodsIds)
                .eq(Goods::getGoodsStatus, GoodsStatus.SHELVED)
        );
    }

    /**
     * 批量更新商品状态
     *
     * @param goodsIds    商品ID列表
     * @param goodsStatus 商品状态
     */
    default void batchModifyGoodsStatus(List<Long> goodsIds, GoodsStatus goodsStatus) {
        this.update(null, Wrappers.<Goods>lambdaUpdate()
                .set(Goods::getGoodsStatus, goodsStatus)
                .in(Goods::getId,goodsIds)
        );
    }

    /**
     * 根据ID查询商品详情
     *
     * @param id 商品ID
     * @return 商品详情
     */
    GoodsVo findGoodsWithCNameById(@Param("id") Long id);

    /**
     * 查询商品分页列表
     *
     * @param goodsPageQuery 具体查询参数
     * @return 分页查询结果
     */
    default PageResponse<GoodsVo> findGoodsWithCNamePage(GoodsPageQuery goodsPageQuery) {
        IPage<GoodsVo> goodsPage = this.findGoodsWithCNamePage(MpPageConvertor.toPage(goodsPageQuery), goodsPageQuery);
        return MpPageConvertor.toPageResponse(goodsPage, Function.identity());
    }

    /**
     * 查询商品分页列表
     *
     * @param page           mp分页参数
     * @param goodsPageQuery 具体查询参数
     * @return 分页查询结果
     */
    @Deprecated
    IPage<GoodsVo> findGoodsWithCNamePage(IPage<GoodsVo> page, @Param("goodsPageQuery") GoodsPageQuery goodsPageQuery);
}
